Skip to content

feat(settings): first-class remote-core connection setting + live status (GH-4396)#4406

Merged
senamakel merged 3 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/GH-4396-remote-core-settings
Jul 3, 2026
Merged

feat(settings): first-class remote-core connection setting + live status (GH-4396)#4406
senamakel merged 3 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/GH-4396-remote-core-settings

Conversation

@M3gA-Mind

@M3gA-Mind M3gA-Mind commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a first-class Settings → Core connection panel that promotes the pre-existing "cloud" core mode (a persisted remote-core RPC URL + bearer token) out of the pre-router BootCheckGate picker and into the running app.
  • Adds a live connect/failure status indicator (the core ask): a status dot + text driven by a real core.ping against the currently-active core, with a Recheck button.
  • Adds a "use remote core" toggle plus URL/token fields with a Test connection button, and a Save & restart action that re-enters the existing boot flow.
  • Reuses existing plumbing (coreModeSlice, configPersistence, testCoreRpcConnection) — no second remote-core mechanism introduced.
  • 12 new settings.core.* i18n keys translated across all 13 locales.

Problem

Pointing the desktop client at a remote openhuman-core was only reachable two ways: the pre-router BootCheckGate picker (first launch / "Switch mode"), or shell-level env vars. Normal Windows launch paths (Start Menu shortcut, openhuman://auth/... deep link) cannot carry those env vars, so the env-var attach path silently fell back to spawning the in-process core, and there was no persistent in-app affordance or visible status for a remote core once past the boot gate. See #4396 (split from #2437-A).

Scope was agreed as promote the existing cloud mode + surface status, not a greenfield build.

Solution

  • CoreConnectionPanel.tsx (new): live status indicator (connected remote/local, token-rejected, unreachable, checking) + Recheck; a SettingsSwitch remote toggle; URL + token fields reusing the BootCheckGate cloud-picker validation and testCoreRpcConnection; and Save & restart which persists via storeRpcUrl/storeCoreToken/storeCoreMode, dispatches setCoreMode, clears the RPC caches, and calls restartApp() so the normal BootCheckGate flow re-runs. Save is gated on a dirty check.
  • Registry + routing: new core entry + <Route path="core">.
  • i18n: settings.core.* keys added to en.ts and all 13 locales with real translations (parity gate green).

Design decisions / tradeoffs:

  • Boot-gate hard-fail/fallback semantics unchanged — the panel only surfaces connection state and re-enters the existing flow on save.
  • Env-var attach path (OPENHUMAN_CORE_REUSE_EXISTING) left as documented dev-only and intentionally not surfaced in the UI.
  • Token stays on the existing localStorage path the cloud picker already uses; an in-code comment references security audit U3 as the known OS-keychain migration follow-up (not blocked here).
  • Deep-link attach?url=&token= import is out of scope (deferred; needs security review — phishing/pivot vector).
  • Env-var naming discrepancy: the issue references OPENHUMAN_CORE_URL, which does not exist in the codebase. The real vars are OPENHUMAN_CORE_RPC_URL (set by the core to advertise its own bound port — internal discovery, not a point-at-remote input) and the build-time VITE_OPENHUMAN_CORE_RPC_URL. The actual user-facing remote-core URL is the persisted cloud-mode URL this panel edits.
  • IA note: there is no "Advanced" settings group in the current registry, so the panel was placed in the General group directly above About (which already shows core mode read-only). Easy to relocate to a dedicated Advanced group if preferred.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) — CoreConnectionPanel.test.tsx: status rendering per mode, reveal toggle, unreachable failure path, and the persist/dispatch/restart save flow.
  • Diff coverage ≥ 80% — Vitest added; measured 131/145 = 90.3% line coverage on CoreConnectionPanel.tsx locally (11 tests). CI diff-cover confirms the merged gate on changed lines.
  • Coverage matrix updated — N/A: no matrix feature row maps to this settings panel (UI surface over existing cloud-mode behaviour).
  • All affected feature IDs listed under ## RelatedN/A: none.
  • No new external network dependencies introduced — no new deps; reuses testCoreRpcConnection (mock-friendly).
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: additive Settings panel, no release-cut surface change.
  • Linked issue closed via Closes #NNN — see ## Related.

Impact

  • Desktop/web: additive Settings panel; no change to existing local/cloud runtime behaviour or the boot gate. Web builds (cloud-only) also get the in-app surface.
  • Security: no new secret exposure beyond the existing cloud-mode localStorage token (audit U3, noted in-code as follow-up); public-HTTP warning reused from the boot picker.
  • Migration/compat: none — reuses existing coreMode slice + configPersistence keys.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/GH-4396-remote-core-settings
  • Commit SHA: c3fa32c

Validation Run

  • pnpm --filter openhuman-app format:check — passes
  • pnpm typecheck — 0 errors in changed files (one pre-existing unrelated error: rehype-highlight missing in AgentMessageBubble.tsx, untouched here)
  • Focused tests: CoreConnectionPanel.test.tsx — 11/11 pass; pnpm --filter openhuman-app lint 0 errors; pnpm i18n:check 0 missing/0 extra across 13 locales
  • Rust fmt/check (if changed): N/A — no Rust changed
  • Tauri fmt/check (if changed): N/A — no Tauri/Rust changed

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: remote-core URL/token become editable from Settings with a live status indicator; switching mode there persists + restarts into the existing boot flow.
  • User-visible effect: new Settings → Core connection panel; no change for users who stay on local mode.

Parity Contract

  • Legacy behavior preserved: BootCheckGate picker, coreMode slice, configPersistence keys, and boot-gate fallback semantics are unchanged.
  • Guard/fallback/dispatch parity checks: save path mirrors the picker's persist + setCoreMode dispatch + cache-clear sequence; env-var attach path untouched.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this
  • Resolution (closed/superseded/updated): N/A

Summary by CodeRabbit

  • New Features

    • Added a new Core Connection settings panel for switching between local and remote core connections.
    • Users can enter a remote URL and token, test the connection, recheck status, and save changes with an automatic app restart.
    • The settings menu now includes a dedicated entry for core connection.
    • Added translated text for the new panel across multiple languages.
  • Bug Fixes

    • Improved connection status feedback with clearer messages for connected, checking, authentication failure, and unreachable states.

@M3gA-Mind M3gA-Mind requested a review from a team July 2, 2026 10:51
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bacc2b0c-d5c7-4021-a5e9-3b6dce54015e

📥 Commits

Reviewing files that changed from the base of the PR and between c0918db and bb52215.

📒 Files selected for processing (18)
  • app/src/components/settings/panels/CoreConnectionPanel.tsx
  • app/src/components/settings/panels/__tests__/CoreConnectionPanel.test.tsx
  • app/src/components/settings/settingsRouteElements.tsx
  • app/src/components/settings/settingsRouteRegistry.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
✅ Files skipped from review due to trivial changes (7)
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/fr.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • app/src/components/settings/settingsRouteElements.tsx
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/es.ts
  • app/src/components/settings/settingsRouteRegistry.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ar.ts

📝 Walkthrough

Walkthrough

Adds a new Core connection settings panel for local/remote core selection, live reachability checks, remote URL/token validation, save-and-restart persistence, settings navigation wiring, tests, and translated UI text.

Changes

Core Connection Panel

Layer / File(s) Summary
Core URL resolution and live status logic
app/src/components/settings/panels/CoreConnectionPanel.tsx
Adds cloud/local RPC URL resolution, live connection status state, and the bounded reachability probe that refreshes on mount and updates.
Input validation, connection test, and save/restart flow
app/src/components/settings/panels/CoreConnectionPanel.tsx
Adds URL/token validation, a one-shot connection test, dirty-state tracking, cache clearing, config persistence, and app restart on save.
Panel UI and tests
app/src/components/settings/panels/CoreConnectionPanel.tsx, app/src/components/settings/panels/__tests__/CoreConnectionPanel.test.tsx
Renders the status indicator, remote toggle, URL/token inputs, test controls, and save action; tests cover live status, switching modes, validation, and persistence flows.
Settings routing and registry wiring
app/src/components/settings/settingsRouteElements.tsx, app/src/components/settings/settingsRouteRegistry.ts
Registers the new core route and adds the matching settings registry entry with navigation metadata and search keywords.
Translations
app/src/lib/i18n/en.ts, app/src/lib/i18n/{ar,bn,de,es,fr,hi,id,it,ko,pl,pt,ru,zh-CN}.ts
Adds settings.core.* strings for the panel title, descriptions, statuses, actions, and restart note across the supported locales.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CoreConnectionPanel
  participant Redux
  participant Tauri
  participant coreRpcClient

  User->>CoreConnectionPanel: open settings panel
  CoreConnectionPanel->>Redux: read cloud core URL
  CoreConnectionPanel->>Tauri: invoke core_rpc_url
  CoreConnectionPanel->>coreRpcClient: testCoreRpcConnection(url)
  coreRpcClient-->>CoreConnectionPanel: live status
  User->>CoreConnectionPanel: click Save
  CoreConnectionPanel->>Redux: update core mode
  CoreConnectionPanel->>Tauri: restartApp()
Loading

Suggested labels: feature

Suggested reviewers: graycyrus

Poem

A rabbit found a core to choose,
Cloud or local, both toూజ? 🐇
It checked the link, then saved its way,
Restarted once to greet the day,
And hopped along with status news.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the new first-class remote-core settings panel and live status feature.
Linked Issues check ✅ Passed The PR implements the requested persisted remote-core URL/token setting, toggle, and live status indicator from #4396.
Out of Scope Changes check ✅ Passed The changes are limited to the new settings panel, routing, tests, and locale strings needed to support it.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c0918dbc17

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +322 to +326
<SettingsSwitch
id="core-use-remote"
checked={useRemote}
onCheckedChange={next => {
setUseRemote(next);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep local mode unavailable in web builds

In non-Tauri web builds the boot picker intentionally forces cloud mode because the browser cannot invoke start_core_process, but this new settings toggle is rendered unconditionally. If a web user turns it off and saves, the local branch persists openhuman_core_mode=local; after reload BootCheck enters local mode and fails trying to start a Tauri-only core, stranding the user on the unreachable recovery screen. Disable/hide the local option when !isTauriEnvironment() so web stays cloud-only.

Useful? React with 👍 / 👎.

</label>
<SettingsTextField
id="core-remote-token"
type="text"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Mask the persisted remote-core token

When a user already has a remote core configured, this field is prefilled from the persisted coreMode.token and rendered as plain text, so simply opening Settings → Core connection exposes the long-lived OPENHUMAN_CORE_TOKEN during screen sharing or shoulder-surfing. Since that bearer grants access to the remote core, render it hidden by default (for example type="password" with an explicit reveal/replace affordance).

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/components/settings/panels/CoreConnectionPanel.tsx`:
- Around line 101-140: The connection checks in runLiveCheck and the manual test
flow are calling testCoreRpcConnection without an AbortSignal, which can leave
the UI stuck in checking/testing on slow or unresponsive endpoints. Add
cancellation/timeout handling by creating and passing an AbortSignal to
testCoreRpcConnection in both paths, and make sure the signal is aborted/cleaned
up when the check is superseded, completes, or times out so the status can
recover promptly.
- Around line 362-371: The bearer token field in CoreConnectionPanel is
currently rendered as plain text, which exposes a secret during normal use.
Update the SettingsTextField for the core token to use a masked password-style
input instead of type="text", and keep any reveal behavior separate if you add
one later. Locate the field by the core-remote-token id in CoreConnectionPanel
and adjust its input type accordingly.
- Around line 154-160: Reject URLs with embedded credentials in
CoreConnectionPanel’s RPC URL validation by checking the parsed URL from new
URL(normalized) for username/password before accepting it. If credentials are
present, set a form error using a new i18n key such as
settings.core.urlCredentialsNotAllowed, and keep the token field as the only
supported credential path. Update the URL validation/normalization flow around
the existing URL parsing logic and ensure the active URL description cannot
render credential-bearing URLs. Add the new translation key through useT() in
en.ts and every locale file.
- Around line 223-253: The handleSave flow in CoreConnectionPanel leaves the UI
stuck if restartApp() rejects because saving is never cleared and the user sees
no error. Wrap the restartApp() call in handleSave with error handling, reset
saving in the failure path, and surface a localized message via useT() using the
new settings.core.restartFailed key. Also add that key to all locale files so
the error text is translated consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: edfe7b02-db04-4680-b6ac-181478c084aa

📥 Commits

Reviewing files that changed from the base of the PR and between f979bfa and c0918db.

📒 Files selected for processing (18)
  • app/src/components/settings/panels/CoreConnectionPanel.tsx
  • app/src/components/settings/panels/__tests__/CoreConnectionPanel.test.tsx
  • app/src/components/settings/settingsRouteElements.tsx
  • app/src/components/settings/settingsRouteRegistry.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts

Comment thread app/src/components/settings/panels/CoreConnectionPanel.tsx
Comment thread app/src/components/settings/panels/CoreConnectionPanel.tsx
Comment thread app/src/components/settings/panels/CoreConnectionPanel.tsx Outdated
Comment thread app/src/components/settings/panels/CoreConnectionPanel.tsx
@M3gA-Mind

Copy link
Copy Markdown
Collaborator Author

Pushed c3fa32c to fix the two red checks.

Frontend Checks (quality, i18n, docs, coverage):

  • Prettier — the panel, its test, settingsRouteElements.tsx, and the 11 edited locale files weren't Prettier-formatted; ran prettier --write on all of them. format:check now passes.
  • ESLint — clean (0 errors). Suppressed one intentional react-hooks/set-state-in-effect warning on the live-check effect, matching existing convention in the codebase.
  • Coverage — changed-line coverage on CoreConnectionPanel.tsx was ~67%, under the 80% diff gate. Added 7 Vitest cases (Test-connection ok/auth/unreachable, live token-rejected + non-ok statuses, validation errors, and the switch-back-to-local save path). Now 131/145 = 90.3% lines, 11/11 tests pass.
  • i18npnpm i18n:check green (0 missing / 0 extra across all 13 locales); typecheck 0 errors.

PR Submission Checklist: filled in the two items that are now honestly verifiable (format:check passes; diff-coverage measured locally at 90.3%) plus the validation-run metadata. 0 unchecked items remain.

No behaviour changed — these are formatting, a lint-annotation, and added tests only. Not merging; that stays with the maintainer.

…tus (tinyhumansaiGH-4396)

Promote the pre-existing cloud core mode (persisted remote-core RPC URL +
bearer token, previously reachable only from the pre-router BootCheckGate
picker) into a first-class Settings > Core connection panel, and add a live
connect/failure status indicator.

- New CoreConnectionPanel: live status dot + Recheck, a 'use remote core'
  toggle, persisted URL + token fields with Test connection, and a
  Save & restart action that re-enters the existing BootCheckGate flow.
- Reuses existing plumbing (coreModeSlice, configPersistence,
  testCoreRpcConnection); does not introduce a second remote-core mechanism.
- Boot-gate hard-fail/fallback semantics unchanged: the panel only surfaces
  connection state.
- Env-var attach path (OPENHUMAN_CORE_REUSE_EXISTING) left as documented
  dev-only; not surfaced in the UI.
- Token stays on the existing localStorage path (audit U3 keychain migration
  noted in-code as a known follow-up).
- Registry + route wiring; 12 new settings.core.* i18n keys translated across
  all 13 locales.
- Vitest coverage for status rendering, the reveal toggle, unreachable state,
  and the persist/dispatch/restart save flow.
- Apply Prettier to the new panel, test, route wiring, and locale files
  (frontend format:check lane was red).
- Suppress the intentional set-state-in-effect lint warning on the live-check
  effect (matches existing convention).
- Add Vitest cases (Test connection ok/auth/unreachable, live auth-rejected +
  non-ok statuses, validation errors, switch-back-to-local save) — raises
  changed-line coverage on CoreConnectionPanel.tsx to ~90% (was ~67%), over
  the 80% diff gate.
@M3gA-Mind M3gA-Mind force-pushed the fix/GH-4396-remote-core-settings branch from c3fa32c to 27e8203 Compare July 3, 2026 15:17
CodeRabbit review on tinyhumansai#4396:
- Gate local mode off in non-Tauri web builds: a browser can't start a local
  core, so the toggle now force-remotes + disables when !isTauriEnvironment(),
  preventing a persisted core_mode=local that bricks the next boot.
- Mask the persisted remote-core token: field is type=password by default with
  a Show/Hide reveal, so opening Settings no longer exposes the bearer during
  screen-sharing/shoulder-surfing.
- Bound the connection checks: testCoreRpcConnection now runs through a
  10s AbortController wrapper (live check + manual Test), so a non-responsive
  endpoint resolves to "unreachable" instead of hanging in checking/testing.
- Reject credentials embedded in the RPC URL (user:pass@host) so a secret can't
  be persisted + echoed back in the active-URL description.
- Recover on restart failure: handleSave wraps restartApp in try/catch and
  resets `saving` (+ surfaces an error) instead of wedging the Save button.

Tests: mock isTauriEnvironment/invoke so desktop-vs-web-build gating is
controllable; new test asserts a web build force-disables the local toggle.
12 tests pass; pnpm typecheck clean.
@coderabbitai coderabbitai Bot added the feature Net-new user-facing capability or product behavior. label Jul 3, 2026
@senamakel senamakel merged commit 1ee92b0 into tinyhumansai:main Jul 3, 2026
19 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Net-new user-facing capability or product behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Attach mode: first-class remote-core URL/token setting + status indicator (from #2437-A)

3 participants